<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

/**
 * 薪资等级模型
 * 管理薪资序列和等级标准
 */
class SalaryGrade extends Model
{
    use HasFactory;

    /**
     * 表名
     */
    protected $table = 'salary_grades';

    /**
     * 可填充字段
     */
    protected $fillable = [
        'code',
        'name',
        'sequence',
        'level',
        'level_name',
        'sort_order',
        'base_salary',
        'salary_min',
        'salary_max',
        'salary_currency',
        'performance_bonus_percentage',
        'allowance_percentage',
        'overtime_rate',
        'min_experience_years',
        'education_requirement',
        'skill_requirements',
        'applicable_positions',
        'applicable_departments',
        'annual_adjustment_rate',
        'effective_date',
        'expiration_date',
        'employee_count',
        'average_salary',
        'status',
        'is_default',
        'approved_by',
        'approved_at',
        'benefits',
        'adjustment_history',
        'notes',
    ];

    /**
     * 字段类型转换
     */
    protected $casts = [
        'level' => 'integer',
        'sort_order' => 'integer',
        'base_salary' => 'decimal:2',
        'salary_min' => 'decimal:2',
        'salary_max' => 'decimal:2',
        'performance_bonus_percentage' => 'decimal:2',
        'allowance_percentage' => 'decimal:2',
        'overtime_rate' => 'decimal:2',
        'min_experience_years' => 'integer',
        'annual_adjustment_rate' => 'decimal:2',
        'effective_date' => 'date',
        'expiration_date' => 'date',
        'approved_at' => 'date',
        'employee_count' => 'integer',
        'average_salary' => 'decimal:2',
        'is_default' => 'boolean',
        'skill_requirements' => 'array',
        'applicable_positions' => 'array',
        'applicable_departments' => 'array',
        'benefits' => 'array',
        'adjustment_history' => 'array',
    ];

    /**
     * 日期字段
     */
    protected $dates = [
        'effective_date',
        'expiration_date',
        'approved_at',
        'created_at',
        'updated_at',
    ];

    // ============ 常量定义 ============

    public const SEQUENCE_ADMINISTRATIVE = 'administrative';
    public const SEQUENCE_TECHNICAL = 'technical';
    public const SEQUENCE_MANAGEMENT = 'management';
    public const SEQUENCE_SALES = 'sales';

    public const STATUS_ACTIVE = 'active';
    public const STATUS_INACTIVE = 'inactive';
    public const STATUS_EXPIRED = 'expired';

    // ============ 关联关系 ============

    /**
     * 关联员工岗位分配
     */
    public function employeePositions(): HasMany
    {
        return $this->hasMany(EmployeeDepartmentPosition::class, 'salary_grade', 'code');
    }

    // ============ 访问器 ============

    /**
     * 获取薪资序列标签
     */
    public function getSequenceLabelAttribute(): string
    {
        return match($this->sequence) {
            self::SEQUENCE_ADMINISTRATIVE => '行政序列',
            self::SEQUENCE_TECHNICAL => '技术序列',
            self::SEQUENCE_MANAGEMENT => '管理序列',
            self::SEQUENCE_SALES => '销售序列',
            default => $this->sequence ?? '未知'
        };
    }

    /**
     * 获取薪资范围
     */
    public function getSalaryRangeAttribute(): string
    {
        if ($this->salary_min && $this->salary_max) {
            return number_format($this->salary_min) . ' - ' . number_format($this->salary_max) . ' ' . $this->salary_currency;
        }
        return number_format($this->base_salary) . ' ' . $this->salary_currency;
    }

    /**
     * 获取绩效奖金金额
     */
    public function getPerformanceBonusAmountAttribute(): ?float
    {
        if (!$this->base_salary || !$this->performance_bonus_percentage) {
            return null;
        }

        return round($this->base_salary * $this->performance_bonus_percentage / 100, 2);
    }

    /**
     * 获取津贴金额
     */
    public function getAllowanceAmountAttribute(): ?float
    {
        if (!$this->base_salary || !$this->allowance_percentage) {
            return null;
        }

        return round($this->base_salary * $this->allowance_percentage / 100, 2);
    }

    /**
     * 获取总薪资上限
     */
    public function getTotalSalaryMaxAttribute(): ?float
    {
        if (!$this->base_salary) {
            return null;
        }

        $total = $this->base_salary;

        if ($this->performance_bonus_percentage) {
            $total += $this->performance_bonus_amount;
        }

        if ($this->allowance_percentage) {
            $total += $this->allowance_amount;
        }

        return round($total, 2);
    }

    /**
     * 获取状态标签
     */
    public function getStatusLabelAttribute(): string
    {
        return match($this->status) {
            self::STATUS_ACTIVE => '生效中',
            self::STATUS_INACTIVE => '已停用',
            self::STATUS_EXPIRED => '已过期',
            default => $this->status ?? '未知'
        };
    }

    /**
     * 获取是否在有效期内
     */
    public function getIsEffectiveAttribute(): bool
    {
        $now = now();

        if ($this->expiration_date && $now->isAfter($this->expiration_date)) {
            return false;
        }

        return $this->status === self::STATUS_ACTIVE;
    }

    /**
     * 获取适用岗位列表
     */
    public function getApplicablePositionsListAttribute(): string
    {
        if (!$this->applicable_positions) {
            return '全部岗位';
        }

        return implode(', ', $this->applicable_positions);
    }

    // ============ 作用域 ============

    /**
     * 生效中作用域
     */
    public function scopeActive($query)
    {
        return $query->where('status', self::STATUS_ACTIVE)
                    ->where(function ($query) {
                        $query->whereNull('expiration_date')
                              ->orWhere('expiration_date', '>', now());
                    });
    }

    /**
     * 默认等级作用域
     */
    public function scopeDefault($query)
    {
        return $query->where('is_default', true);
    }

    /**
     * 按序列筛选作用域
     */
    public function scopeBySequence($query, $sequence)
    {
        return $query->where('sequence', $sequence);
    }

    /**
     * 按等级排序作用域
     */
    public function scopeOrderByLevel($query)
    {
        return $query->orderBy('sequence')->orderBy('level');
    }

    /**
     * 按薪资排序作用域
     */
    public function scopeOrderBySalary($query)
    {
        return $query->orderBy('base_salary');
    }

    // ============ 业务方法 ============

    /**
     * 激活薪资等级
     */
    public function activate(): bool
    {
        $this->status = self::STATUS_ACTIVE;
        return $this->save();
    }

    /**
     * 停用薪资等级
     */
    public function deactivate(): bool
    {
        $this->status = self::STATUS_INACTIVE;
        return $this->save();
    }

    /**
     * 设置为默认等级
     */
    public function setAsDefault(): bool
    {
        // 取消其他默认等级
        self::where('sequence', $this->sequence)
            ->where('id', '!=', $this->id)
            ->update(['is_default' => false]);

        $this->is_default = true;
        return $this->save();
    }

    /**
     * 更新薪资标准
     */
    public function updateSalary(float $baseSalary, ?float $min = null, ?float $max = null): bool
    {
        $this->base_salary = $baseSalary;
        $this->salary_min = $min;
        $this->salary_max = $max;

        // 记录调整历史
        $this->recordAdjustment('salary', '薪资标准调整', [
            'previous_base' => $this->getOriginal('base_salary'),
            'new_base' => $baseSalary,
            'previous_min' => $this->getOriginal('salary_min'),
            'new_min' => $min,
            'previous_max' => $this->getOriginal('salary_max'),
            'new_max' => $max,
        ]);

        return $this->save();
    }

    /**
     * 添加适用岗位
     */
    public function addApplicablePosition(string $position): bool
    {
        $positions = $this->applicable_positions ?? [];
        if (!in_array($position, $positions)) {
            $positions[] = $position;
            $this->applicable_positions = $positions;
            return $this->save();
        }
        return true;
    }

    /**
     * 移除适用岗位
     */
    public function removeApplicablePosition(string $position): bool
    {
        $positions = $this->applicable_positions ?? [];
        $positions = array_diff($positions, [$position]);
        $this->applicable_positions = array_values($positions);
        return $this->save();
    }

    /**
     * 检查岗位是否适用
     */
    public function isApplicableToPosition(string $position): bool
    {
        if (empty($this->applicable_positions)) {
            return true; // 如果没有设置适用岗位，则适用于所有岗位
        }

        return in_array($position, $this->applicable_positions);
    }

    /**
     * 记录调整历史
     */
    public function recordAdjustment(string $type, string $reason, array $details): bool
    {
        $history = $this->adjustment_history ?? [];
        $history[] = [
            'type' => $type,
            'reason' => $reason,
            'details' => $details,
            'adjusted_at' => now()->toISOString(),
            'adjusted_by' => auth()->id() ?? null,
        ];

        $this->adjustment_history = $history;
        return $this->save();
    }

    /**
     * 更新统计信息
     */
    public function updateStatistics(): bool
    {
        $employeeCount = $this->employeePositions()->count();
        $averageSalary = $this->employeePositions()->avg('base_salary');

        $this->employee_count = $employeeCount;
        $this->average_salary = $averageSalary;

        return $this->save();
    }

    // ============ 静态方法 ============

    /**
     * 获取薪资序列选项
     */
    public static function getSequenceOptions(): array
    {
        return [
            self::SEQUENCE_ADMINISTRATIVE => '行政序列',
            self::SEQUENCE_TECHNICAL => '技术序列',
            self::SEQUENCE_MANAGEMENT => '管理序列',
            self::SEQUENCE_SALES => '销售序列',
        ];
    }

    /**
     * 创建默认薪资等级
     */
    public static function createDefaultGrades(): array
    {
        $grades = [];

        // 行政序列：基本工资2100，10个档，每档间隔100
        for ($i = 1; $i <= 10; $i++) {
            $baseSalary = 2100 + ($i - 1) * 100;
            $grades[] = [
                'code' => 'ADMIN_' . str_pad($i, 2, '0', STR_PAD_LEFT),
                'name' => '行政序列' . $i . '级',
                'sequence' => self::SEQUENCE_ADMINISTRATIVE,
                'level' => $i,
                'level_name' => $i . '级',
                'base_salary' => $baseSalary,
                'salary_min' => $baseSalary - 50,
                'salary_max' => $baseSalary + 50,
                'performance_bonus_percentage' => 20,
                'allowance_percentage' => 10,
                'min_experience_years' => max(0, $i - 1),
                'effective_date' => now(),
                'status' => self::STATUS_ACTIVE,
                'is_default' => $i === 1,
            ];
        }

        // 技术序列：基本工资2500，20个档，每档间隔120
        for ($i = 1; $i <= 20; $i++) {
            $baseSalary = 2500 + ($i - 1) * 120;
            $grades[] = [
                'code' => 'TECH_' . str_pad($i, 2, '0', STR_PAD_LEFT),
                'name' => '技术序列' . $i . '级',
                'sequence' => self::SEQUENCE_TECHNICAL,
                'level' => $i,
                'level_name' => $i . '级',
                'base_salary' => $baseSalary,
                'salary_min' => $baseSalary - 60,
                'salary_max' => $baseSalary + 60,
                'performance_bonus_percentage' => 25,
                'allowance_percentage' => 15,
                'min_experience_years' => max(0, $i - 1),
                'effective_date' => now(),
                'status' => self::STATUS_ACTIVE,
                'is_default' => false,
            ];
        }

        $createdGrades = [];
        foreach ($grades as $gradeData) {
            $grade = self::create($gradeData);
            $createdGrades[] = $grade;
        }

        return $createdGrades;
    }

    /**
     * 获取薪资等级建议
     */
    public static function getRecommendedGrade(
        string $sequence,
        int $experienceYears,
        string $educationLevel = null
    ): ?self {
        $query = self::where('sequence', $sequence)
                    ->where('status', self::STATUS_ACTIVE)
                    ->where('min_experience_years', '<=', $experienceYears)
                    ->orderBy('level', 'desc');

        // 根据学历调整等级
        if ($educationLevel) {
            // 更高学历可以获得更高等级
            $educationBonus = match($educationLevel) {
                'bachelor' => 1,
                'master' => 2,
                'doctor' => 3,
                default => 0,
            };

            $adjustedExperience = $experienceYears + $educationBonus;
            $query->where('min_experience_years', '<=', $adjustedExperience);
        }

        return $query->first();
    }

    /**
     * 验证薪资等级数据
     */
    public static function validateGradeData(array $data): array
    {
        $errors = [];

        // 必填字段验证
        $requiredFields = ['code', 'name', 'sequence', 'base_salary'];
        foreach ($requiredFields as $field) {
            if (empty($data[$field])) {
                $errors[] = "{$field} 字段不能为空";
            }
        }

        // 编码唯一性验证
        if (!empty($data['code'])) {
            $query = self::where('code', $data['code']);
            if (isset($data['id'])) {
                $query->where('id', '!=', $data['id']);
            }
            if ($query->exists()) {
                $errors[] = "编码 {$data['code']} 已存在";
            }
        }

        // 薪资序列验证
        $validSequences = array_keys(self::getSequenceOptions());
        if (!empty($data['sequence']) && !in_array($data['sequence'], $validSequences)) {
            $errors[] = "无效的薪资序列";
        }

        // 数值验证
        if (!empty($data['base_salary']) && (!is_numeric($data['base_salary']) || $data['base_salary'] <= 0)) {
            $errors[] = "基本薪资必须是有效的正数";
        }

        if (!empty($data['performance_bonus_percentage']) && (!is_numeric($data['performance_bonus_percentage']) || $data['performance_bonus_percentage'] < 0 || $data['performance_bonus_percentage'] > 100)) {
            $errors[] = "绩效奖金比例必须在0-100之间";
        }

        // 薪资范围验证
        if (!empty($data['salary_min']) && !empty($data['salary_max']) && $data['salary_min'] >= $data['salary_max']) {
            $errors[] = "薪资下限必须小于薪资上限";
        }

        return $errors;
    }
}
